package com.relife.common.utils;

import java.beans.PropertyDescriptor;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.BeanUtils;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

public class XmlUtil {

	/**
	 * 流转XML
	 * 
	 * @author WU
	 * @date 2015年12月3日 下午2:11:03
	 * @param inputStream
	 * @return
	 * @throws Exception
	 */
	public static Map<String, String> parseXml(InputStream inputStream) throws Exception {
		// 将解析结果存储在HashMap中
		Map<String, String> map = new HashMap<String, String>();

		// 读取输入流
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		// 得到xml根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子节点
		@SuppressWarnings("unchecked")
		List<Element> elementList = root.elements();

		// 遍历所有子节点
		for (Element e : elementList)
			map.put(e.getName(), e.getText());

		// 释放资源
		inputStream.close();
		inputStream = null;

		return map;
	}

	/***
	 * XML流转对象
	 * 
	 * @author WU
	 * @date 2015年12月3日 下午2:15:11
	 * @param in
	 * @param cl
	 * @return
	 */
	public static <T> T get(InputStream in, Class<T> cl) {
		try {
			T t = cl.newInstance();
			Map<String, String> map = parseXml(in);
			PropertyDescriptor pro[] = BeanUtils.getPropertyDescriptors(t.getClass());
			for (int i = 0; i < pro.length; i++) {
				if (map.containsKey(pro[i].getName())) {
					try {
						pro[i].getWriteMethod().invoke(t, map.get(pro[i].getName()));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
			return t;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/***
	 * 扩展xstream，使其支持CDATA块
	 * 
	 * @author WU
	 * @date 2015-5-1 下午3:39:05
	 */
	@SuppressWarnings("rawtypes")
	public static XStream xstream = new XStream(new XppDriver() {
		public HierarchicalStreamWriter createWriter(Writer out) {
			return new PrettyPrintWriter(out) {
				// 对所有xml节点的转换都增加CDATA标记
				boolean cdata = true;

				public void startNode(String name, Class clazz) {
					super.startNode(name, clazz);
				}

				protected void writeText(QuickWriter writer, String text) {
					if (cdata) {
						writer.write("<![CDATA[");
						writer.write(text);
						writer.write("]]>");
					} else {
						writer.write(text);
					}
				}
			};
		}
	});
}
